package com.jdy.haoduoaiteacher.pulltorefresh;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.ycsj.goldmedalnewconcept.R;

import java.util.Timer;
import java.util.TimerTask;

//import com.jdy.haoduoaiteacher.R;

/**
 * 自定义的布局，用来管理三个子控件，其中一个是下拉头，一个是包含内容的pullableView（可以是实现Pullable接口的的任何View），
 * 
 */
@SuppressLint("HandlerLeak")
public class PullToRefreshLayout extends RelativeLayout {
  public static final String TAG = "PullToRefreshLayout";
  // 初始状态
  public static final int INIT = 0;
  // 释放刷新
  public static final int RELEASE_TO_REFRESH = 1;
  // 正在刷新
  public static final int REFRESHING = 2;
  // 释放加载
  public static final int RELEASE_TO_LOAD = 3;
  // 正在加载
  public static final int LOADING = 4;
  // 操作完毕
  public static final int DONE = 5;
  // 当前状态
  private int state = INIT;
  // 刷新回调接口
  private OnRefreshListener mListener;

  public static final int LOAD_COMPLETED = 7;

  // 刷新成功
  public static final int SUCCEED = 0;
  // 刷新失败
  public static final int FAIL = 1;
  // 按下Y坐标，上一个事件点Y坐标
  private float downY, lastY;
  private float downX, lastX;
  // 下拉的距离。注意：pullDownY和pullUpY不可能同时不为0
  public float pullDownY = 0;
  // 上拉的距离
  private float pullUpY = 0;

  // 释放刷新的距离
  private float refreshDist = 200;
  // 释放加载的距离
  private float loadmoreDist = 200;

  private MyTimer timer;
  // 回滚速度
  public float MOVE_SPEED = 8;
  // 第一次执行布局
  private boolean isLayout = false;
  // 在刷新过程中滑动操作
  private boolean isTouch = false;
  // 手指滑动距离与下拉头的滑动距离比，中间会随正切函数变化
  private float radio = 2;

  // 下拉箭头的转180°动画
  private RotateAnimation rotateAnimation;

  private AnimationDrawable refreshingAnim;
  // private Animation mRefreshAnimation;
  // 均匀旋转动画
  // private RotateAnimation refreshingAnimation;

  // 下拉头
  private View refreshHeadView;
  // 下拉的箭头
  private View pullDownIcon;
  // 正在刷新的图标
  private View refreshingIcon;
  // 刷新结果图标
  private View refreshResultIcon;
  // 刷新结果：成功或失败
  private TextView refreshResultTxt;

  // 上拉头
  private View loadmoreView;
  // 上拉的箭头
  private View pullUpIcon;
  // 正在加载的图标
  private View loadingIcon;
  // 加载结果图标
  private View loadResultIcon;
  // 加载结果：成功或失败
  private TextView loadResultTxt;

  // 实现了Pullable接口的View
  private View pullableView;
  // 过滤多点触碰
  private int mEvents;
  // 这两个变量用来控制pull的方向，如果不加控制，当情况满足可上拉又可下拉时没法下拉
  private boolean canPullDown = true;
  private boolean canPullUp = true;

  long endTime, beginTime;

  private Context mContext;

  /**
   * 执行自动回滚的handler
   */
  Handler updateHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {
      // 回弹速度随下拉距离moveDeltaY增大而增大
      MOVE_SPEED = (float) (8 + 5 * Math.tan(Math.PI / 2 / getMeasuredHeight()
          * (pullDownY + Math.abs(pullUpY))));
      if (!isTouch) {
        // 正在刷新，且没有往上推的话则悬停，显示"正在刷新..."
        if (state == REFRESHING && pullDownY <= refreshDist) {
          pullDownY = refreshDist;
          timer.cancel();
        } else if (state == LOADING && -pullUpY <= loadmoreDist) {
          pullUpY = -loadmoreDist;
          timer.cancel();
        }

      }
      if (pullDownY > 0)
        pullDownY -= MOVE_SPEED;
      else if (pullUpY < 0)
        pullUpY += MOVE_SPEED;
      if (pullDownY < 0) {
        // 已完成回弹
        pullDownY = 0;
        // pullView.clearAnimation();
        ((ImageView) pullDownIcon).setImageResource(R.drawable.loading_pic_00);
        // 隐藏下拉头时有可能还在刷新，只有当前状态不是正在刷新时才改变状态
        if (state != REFRESHING && state != LOADING)
          changeState(INIT);
        timer.cancel();
        requestLayout();
      }
      if (pullUpY > 0) {
        // 已完成回弹
        pullUpY = 0;
        pullUpIcon.clearAnimation();
        // 隐藏上拉头时有可能还在刷新，只有当前状态不是正在刷新时才改变状态
        if (state != REFRESHING && state != LOADING)
          changeState(INIT);
        timer.cancel();
        requestLayout();
      }
      Log.d("handle", "handle");
      // 刷新布局,会自动调用onLayout
      requestLayout();
      // 没有拖拉或者回弹完成
      if (pullDownY + Math.abs(pullUpY) == 0)
        timer.cancel();
    }

  };

  public void setOnRefreshListener(OnRefreshListener listener) {
    mListener = listener;
  }

  public PullToRefreshLayout(Context context) {
    super(context);
    initView(context);
  }

  public PullToRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView(context);
  }

  public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initView(context);
  }

  private void initView(Context context) {
    mContext = context;
    timer = new MyTimer(updateHandler);
    rotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(context,
        R.anim.reverse_anim);
    // refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(
    // context, R.anim.rotating);

    // refreshingView.setBackgroundResource(R.drawable.anim_loading);
    // refreshingAnim = (AnimationDrawable) refreshingView.getBackground();
    // mAnim.start();

    // 添加匀速转动动画
    LinearInterpolator lir = new LinearInterpolator();
    rotateAnimation.setInterpolator(lir);
    // refreshingAnimation.setInterpolator(lir);
  }

  private void hide() {
    timer.schedule(5);
  }

  Handler mHandler;

  /**
   * 完成刷新操作，显示刷新结果。注意：刷新完成后一定要调用这个方法
   */
  /**
   * @param refreshResult
   *          PullToRefreshLayout.SUCCEED代表成功，PullToRefreshLayout.FAIL代表失败
   */
  public void refreshFinish(final int refreshResult) {

    endTime = System.currentTimeMillis();

    long interval = (endTime - beginTime);

    long finishDelay = 0;
    if (interval < 3000) {
      finishDelay = 3000 - interval;
    } else {
      // TODO
    }

    if (mHandler != null) {
      mHandler.removeCallbacksAndMessages(null);
    } else {
      mHandler = new Handler();
    }

    mHandler.postDelayed(new Runnable() {

      @Override
      public void run() {
        // refreshingView.clearAnimation();
        // refreshingView.setVisibility(View.GONE);

        switch (refreshResult) {
        case LOAD_COMPLETED:
          refreshResultTxt.setText("已经加载完毕");
          refreshResultIcon.setBackgroundResource(R.drawable.refresh_succeed);
          break;
        case SUCCEED:
          // 刷新成功
          // refreshStateImageView.setVisibility(View.VISIBLE);
          refreshResultTxt.setText(R.string.refresh_succeed);
          refreshResultIcon.setBackgroundResource(R.drawable.refresh_succeed);
          break;
        case FAIL:
        default:
          // 刷新失败
          // refreshStateImageView.setVisibility(View.VISIBLE);
          refreshResultTxt.setText(R.string.refresh_fail);
          refreshResultIcon.setBackgroundResource(R.drawable.refresh_failed);
          break;
        }
        if (pullDownY > 0) {
          // 刷新结果停留1秒
          new Handler() {
            @Override
            public void handleMessage(Message msg) {
              changeState(DONE);
              hide();

              refreshingIcon.clearAnimation();
              refreshingIcon.setVisibility(View.GONE);
            }
          }.sendEmptyMessageDelayed(0, 1000);
        } else {
          changeState(DONE);
          hide();

          refreshingIcon.clearAnimation();
          refreshingIcon.setVisibility(View.GONE);
        }

      }
    }, finishDelay);

  }

  /**
   * 加载完毕，显示加载结果。注意：加载完成后一定要调用这个方法
   * 
   * @param refreshResult
   *          PullToRefreshLayout.SUCCEED代表成功，PullToRefreshLayout.FAIL代表失败
   */
  public void loadmoreFinish(int refreshResult) {

    if (loadingIcon != null) {
      loadingIcon.clearAnimation();
      loadingIcon.setVisibility(View.GONE);
    }

    switch (refreshResult) {

    case LOAD_COMPLETED:
      // 加载成功
      loadResultIcon.setVisibility(View.VISIBLE);
      loadResultTxt.setText("已经加载完毕");
      loadResultIcon.setBackgroundResource(R.drawable.load_succeed);
      break;

    case SUCCEED:
      // 加载成功
      loadResultIcon.setVisibility(View.VISIBLE);
      loadResultTxt.setText(R.string.load_succeed);
      loadResultIcon.setBackgroundResource(R.drawable.load_succeed);
      break;
    case FAIL:
    default:
      // 加载失败
      loadResultIcon.setVisibility(View.VISIBLE);
      loadResultTxt.setText(R.string.load_fail);
      loadResultIcon.setBackgroundResource(R.drawable.load_failed);
      break;
    }
    if (pullUpY < 0) {
      // 刷新结果停留1秒
      new Handler() {
        @Override
        public void handleMessage(Message msg) {
          changeState(DONE);
          hide();
        }
      }.sendEmptyMessageDelayed(0, 1000);
    } else {
      changeState(DONE);
      hide();
    }
  }

  public void changeState(int to) {
    state = to;
    switch (state) {
    case INIT:
      // 下拉布局初始状态

      if (loadingIcon != null) {
        loadingIcon.setVisibility(View.GONE);
      }

      refreshResultIcon.setVisibility(View.GONE);
      refreshResultTxt.setText(R.string.pull_to_refresh);
      // pullView.clearAnimation();
      ((ImageView) pullDownIcon).setImageResource(R.drawable.loading_pic_00);
      pullDownIcon.setVisibility(View.VISIBLE);
      // 上拉布局初始状态
      loadResultIcon.setVisibility(View.GONE);
      loadResultTxt.setText(R.string.pullup_to_load);
      pullUpIcon.clearAnimation();
      pullUpIcon.setVisibility(View.VISIBLE);

      if (refreshingIcon != null) {
        refreshingIcon.clearAnimation();
        refreshingIcon.setVisibility(View.GONE);
      }

      beginTime = System.currentTimeMillis();
      break;
    case RELEASE_TO_REFRESH:
      // 释放刷新状态
      refreshResultTxt.setText(R.string.release_to_refresh);
      // pullView.startAnimation(rotateAnimation);

      ((ImageView) pullDownIcon).setImageResource(R.drawable.loading_pic_00);
      break;
    case REFRESHING:

      // if (refreshingView != null) {
      // refreshingView.clearAnimation();
      // refreshingView.setVisibility(View.GONE);
      // }
      //
      // beginTime = System.currentTimeMillis();

      // 正在刷新状态
      // pullView.clearAnimation();
      refreshingIcon.setVisibility(View.VISIBLE);
      // pullView.setVisibility(View.INVISIBLE);

      ((ImageView) pullDownIcon).setImageResource(R.drawable.loading_pic_00);

      // refreshingView.startAnimation(refreshingAnimation);

      pullDownIcon.setVisibility(View.GONE);
      refreshingAnim.start();
      // refreshingView.startAnimation(mRefreshAnimation);

      refreshResultTxt.setText(R.string.refreshing);
      break;
    case RELEASE_TO_LOAD:
      // 释放加载状态
      if (loadingIcon != null) {
        loadingIcon.setVisibility(View.GONE);
      }
      loadResultTxt.setText(R.string.release_to_load);
      pullUpIcon.startAnimation(rotateAnimation);
      break;
    case LOADING:

      // if (refreshingView != null) {
      // refreshingView.clearAnimation();
      // refreshingView.setVisibility(View.GONE);
      // }
      //
      // beginTime = System.currentTimeMillis();
      // 正在加载状态
      pullUpIcon.clearAnimation();
      loadingIcon.setVisibility(View.VISIBLE);
      pullUpIcon.setVisibility(View.INVISIBLE);
      pullDownIcon.setVisibility(View.GONE);

      // loadingIcon.startAnimation(refreshingAnimation);
      refreshingAnim.start();
      // refreshingView.startAnimation(mRefreshAnimation);

      loadResultTxt.setText(R.string.loading);
      break;
    case DONE:
      // 刷新或加载完毕，啥都不做
      break;
    }
  }

  /**
   * 不限制上拉或下拉
   */
  private void releasePull() {
    canPullDown = true;
    canPullUp = true;

    // if (mHandler != null) {
    // mHandler.removeCallbacksAndMessages(null);
    // }

    // if (refreshingView != null) {
    // refreshingView.clearAnimation();
    // refreshingView.setVisibility(View.GONE);
    // }
    //
    // beginTime = System.currentTimeMillis();

  }

  /*
   * （非 Javadoc）由父控件决定是否分发事件，防止事件冲突
   * 
   * @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent)
   */
  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getActionMasked()) {
    case MotionEvent.ACTION_DOWN:
      downY = ev.getY();
      downX = ev.getX();
      lastY = downY;
      lastX = downX;
      timer.cancel();
      mEvents = 0;
      releasePull();
      break;
    case MotionEvent.ACTION_POINTER_DOWN:
    case MotionEvent.ACTION_POINTER_UP:
      // 过滤多点触碰
      mEvents = -1;
      break;
    case MotionEvent.ACTION_MOVE:
      if (mEvents == 0) {
        int absX = (int) Math.abs(ev.getX() - lastX);
        int absY = (int) Math.abs(ev.getY() - lastY);

        if (pullDownY > 0
            || (((Pullable) pullableView).canPullDown() && canPullDown
                && state != LOADING && absY > absX)) {
          // 可以下拉，正在加载时不能下拉
          // 对实际滑动距离做缩小，造成用力拉的感觉
          pullDownY = pullDownY + (ev.getY() - lastY) / radio;
          if (pullDownY < 0) {
            pullDownY = 0;
            canPullDown = false;
            canPullUp = true;
          }
          if (pullDownY > getMeasuredHeight())
            pullDownY = getMeasuredHeight();
          if (state == REFRESHING) {
            // 正在刷新的时候触摸移动
            isTouch = true;
          }
        } else if (pullUpY < 0
            || (((Pullable) pullableView).canPullUp() && canPullUp && state != REFRESHING)) {
          // 可以上拉，正在刷新时不能上拉
          pullUpY = pullUpY + (ev.getY() - lastY) / radio;
          if (pullUpY > 0) {
            pullUpY = 0;
            canPullDown = true;
            canPullUp = false;
          }
          if (pullUpY < -getMeasuredHeight())
            pullUpY = -getMeasuredHeight();
          if (state == LOADING) {
            // 正在加载的时候触摸移动
            isTouch = true;
          }
        } else
          releasePull();
      } else
        mEvents = 0;
      lastY = ev.getY();
      // 根据下拉距离改变比例
      radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight()
          * (pullDownY + Math.abs(pullUpY))));
      if (pullDownY > 0 || pullUpY < 0)
        requestLayout();
      if (pullDownY > 0) {
        if (pullDownY <= refreshDist
            && (state == RELEASE_TO_REFRESH || state == DONE)) {
          // 如果下拉距离没达到刷新的距离且当前状态是释放刷新，改变状态为下拉刷新
          changeState(INIT);
        }
        if (pullDownY >= refreshDist && state == INIT) {
          // 如果下拉距离达到刷新的距离且当前状态是初始状态刷新，改变状态为释放刷新
          changeState(RELEASE_TO_REFRESH);
        }
      } else if (pullUpY < 0) {
        // 下面是判断上拉加载的，同上，注意pullUpY是负值
        if (-pullUpY <= loadmoreDist
            && (state == RELEASE_TO_LOAD || state == DONE)) {
          changeState(INIT);
        }
        // 上拉操作
        if (-pullUpY >= loadmoreDist && state == INIT) {
          changeState(RELEASE_TO_LOAD);
        }

      }
      // 因为刷新和加载操作不能同时进行，所以pullDownY和pullUpY不会同时不为0，因此这里用(pullDownY +
      // Math.abs(pullUpY))就可以不对当前状态作区分了
      if ((pullDownY + Math.abs(pullUpY)) > 8) {
        // 防止下拉过程中误触发长按事件和点击事件
        ev.setAction(MotionEvent.ACTION_CANCEL);
      }
      break;
    case MotionEvent.ACTION_UP:
      if (pullDownY > refreshDist || -pullUpY > loadmoreDist)
      // 正在刷新时往下拉（正在加载时往上拉），释放后下拉头（上拉头）不隐藏
      {
        isTouch = false;
      }
      if (state == RELEASE_TO_REFRESH) {
        changeState(REFRESHING);
        // 刷新操作
        if (mListener != null)
          mListener.onRefresh(this);
      } else if (state == RELEASE_TO_LOAD) {
        changeState(LOADING);
        // 加载操作
        if (mListener != null)
          mListener.onLoadMore(this);
      }
      hide();
    default:
      break;
    }
    // 事件分发交给父类
    super.dispatchTouchEvent(ev);
    return true;
  }

  /**
   * 自动模拟手指滑动的task
   * 
   */
  private class AutoRefreshAndLoadTask extends
      AsyncTask<Integer, Float, String> {

    @Override
    protected String doInBackground(Integer... params) {
      while (pullDownY < 4 / 3 * refreshDist) {
        pullDownY += MOVE_SPEED;
        publishProgress(pullDownY);
        try {
          Thread.sleep(params[0]);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      return null;
    }

    @Override
    protected void onPostExecute(String result) {
      changeState(REFRESHING);
      // 刷新操作
      if (mListener != null)
        mListener.onRefresh(PullToRefreshLayout.this);
      hide();
    }

    @Override
    protected void onProgressUpdate(Float... values) {
      if (pullDownY > refreshDist)
        changeState(RELEASE_TO_REFRESH);
      requestLayout();
    }

  }

  /**
   * 自动刷新
   */
  // public void autoRefresh() {
  // AutoRefreshAndLoadTask task = new AutoRefreshAndLoadTask();
  // task.execute(20);
  // }

  /**
   * 自动加载
   */
  // public void autoLoad() {
  // pullUpY = -loadmoreDist;
  // requestLayout();
  // changeState(LOADING);
  // // 加载操作
  // if (mListener != null)
  // mListener.onLoadMore(this);
  // }

  private void initView() {
    // 初始化下拉布局
    pullDownIcon = refreshHeadView.findViewById(R.id.pull_icon);
    refreshResultTxt = (TextView) refreshHeadView.findViewById(R.id.state_tv);
    refreshingIcon = refreshHeadView.findViewById(R.id.refreshing_icon);
    refreshResultIcon = refreshHeadView.findViewById(R.id.state_iv);
    // 初始化上拉布局
    pullUpIcon = loadmoreView.findViewById(R.id.pullup_icon);
    loadResultTxt = (TextView) loadmoreView.findViewById(R.id.loadstate_tv);
    loadingIcon = loadmoreView.findViewById(R.id.loading_icon);
    loadResultIcon = loadmoreView.findViewById(R.id.loadstate_iv);

    refreshingIcon.setBackgroundResource(R.drawable.anim_loading_3);
    refreshingAnim = (AnimationDrawable) refreshingIcon.getBackground();

    // mRefreshAnimation = AnimationUtils.loadAnimation(MyTeacherApp
    // .getInstance().getAppContext(), R.anim.anim_loading);
  }

  // 0xffdde9f0
  public void setHeadColor(int color) {
    if (refreshHeadView != null)
      refreshHeadView.setBackgroundColor(color);
  }

  public void setTailColor(int color) {
    if (loadmoreView != null)
      loadmoreView.setBackgroundColor(color);
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    Log.d("Test", "Test");
    if (isInEditMode()) {
      return;
    }
    if (!isLayout) {
      // 这里是第一次进来的时候做一些初始化
      refreshHeadView = getChildAt(0);
      pullableView = getChildAt(1);
      loadmoreView = getChildAt(2);
      isLayout = true;
      initView();
      refreshDist = ((ViewGroup) refreshHeadView).getChildAt(0)
          .getMeasuredHeight();
      loadmoreDist = ((ViewGroup) loadmoreView).getChildAt(0)
          .getMeasuredHeight();
    }
    // 改变子控件的布局，这里直接用(pullDownY + pullUpY)作为偏移量，这样就可以不对当前状态作区分
    refreshHeadView.layout(0,
        (int) (pullDownY + pullUpY) - refreshHeadView.getMeasuredHeight(),
        refreshHeadView.getMeasuredWidth(), (int) (pullDownY + pullUpY));
    pullableView.layout(0, (int) (pullDownY + pullUpY),
        pullableView.getMeasuredWidth(), (int) (pullDownY + pullUpY)
            + pullableView.getMeasuredHeight());
    loadmoreView.layout(0,
        (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight(),
        loadmoreView.getMeasuredWidth(),
        (int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight()
            + loadmoreView.getMeasuredHeight());
  }

  class MyTimer {
    private final Handler handler;
    private final Timer timer;
    private MyTask mTask;

    public MyTimer(Handler handler) {
      this.handler = handler;
      timer = new Timer();
    }

    public void schedule(long period) {
      if (mTask != null) {
        mTask.cancel();
        mTask = null;
      }
      mTask = new MyTask(handler);
      timer.schedule(mTask, 0, period);
    }

    public void cancel() {
      if (mTask != null) {
        mTask.cancel();
        mTask = null;
      }
    }

    class MyTask extends TimerTask {
      private final Handler handler;

      public MyTask(Handler handler) {
        this.handler = handler;
      }

      @Override
      public void run() {
        handler.obtainMessage().sendToTarget();
      }

    }
  }

  /**
   * 刷新加载回调接口
   * 
   * 
   */
  public interface OnRefreshListener {
    /**
     * 刷新操作
     */
    void onRefresh(PullToRefreshLayout pullToRefreshLayout);

    /**
     * 加载操作
     */
    void onLoadMore(PullToRefreshLayout pullToRefreshLayout);
  }

}
